
import shadowDepth from '../shader/shadowDepth.wgsl?raw'
import ShadowPipelineInfo from '../interface/shadowPipelineInfo'


async function createShadowPipeline(device: GPUDevice) : Promise<ShadowPipelineInfo> {

    const vertexBuffers: Iterable<GPUVertexBufferLayout> = [{
        arrayStride: 8 * 4, // 3 position 2 uv,
        attributes: [
            {
                // position
                shaderLocation: 0,
                offset: 0,
                format: 'float32x3',
            },
            {
                // normal
                shaderLocation: 1,
                offset: 3 * 4,
                format: 'float32x3',
            },
            {
                // uv
                shaderLocation: 2,
                offset: 6 * 4,
                format: 'float32x2',
            },
        ]
    }]
    const primitive = {
        topology: 'triangle-list',
        cullMode: 'back'
    }
    const depthStencil = {
        depthWriteEnabled: true,
        depthCompare: 'less',
        format: 'depth32float',
    }
    const shadowPipeline = await device.createRenderPipelineAsync({
        label: 'Shadow Pipline',
        layout: 'auto',
        vertex: {
            module: device.createShaderModule({
                code: shadowDepth,
            }),
            entryPoint: 'main',
            buffers: vertexBuffers
        },
        primitive, depthStencil
    } as GPURenderPipelineDescriptor)
    // create a depthTexture for shadow
    const shadowDepthTexture = device.createTexture({
        size: [2048, 2048],
        usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
        format: 'depth32float'
    });

    // create depthTextureView
    const shadowDepthView = shadowDepthTexture.createView()

    // create a 4x4 uniform buffer to store projection
    const lightProjectionBuffer = device.createBuffer({
        label: 'GPUBuffer for light projection',
        size: 4 * 4 * 4, // 4 x 4 x float32
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    })

    return {
        pipeline: shadowPipeline,
        depthTexture: shadowDepthTexture,
        depthView: shadowDepthView,
        lightProjectionBuffer,
    }
}

export { createShadowPipeline }